home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / VideoToolboxSources / SetOnePixel.c < prev    next >
Text File  |  1995-07-27  |  10KB  |  305 lines

  1. /*
  2. SetOnePixel.c
  3. NOTE: These routines are obsolete, retained solely for backward compatibility. 
  4. Use SetPixelsQuickly.c instead, since it's more than ten times faster in 
  5. most applications.
  6.  
  7. These are replacements for the official Apple SetCPixel, etc. Their virtue is
  8. that they're faster (but still slow) and don't translate your index via the
  9. color table. GetxxxPixel & SetxxxPixel all ignore the color spec arrays, giving
  10. you direct access to the unsigned number stored in the pixel (whether 1, 2, 4,
  11. 8, 16, or 32 bits)..
  12.  
  13. SetOnePixel(x,y,value);
  14. value=GetOnePixel(x,y);
  15. They use the current port. x and y are local coordinates.
  16.  
  17. SetPixmapPixel() and GetPixmapPixel() use the specified pixmap or bitmap.
  18.  
  19. SetDevicePixel() and GetDevicePixel() use the specified graphics device (i.e.
  20. monitor).
  21.  
  22. NOTE:
  23. If you are setting many contiguous pixels you will be wasting most of your time
  24. on the call overhead (once per pixel). That's why you should use
  25. SetPixelsQuickly.c instead.
  26.  
  27. These routines (and RectToAddress) do not "move memory", i.e. they don't give the
  28. Memory Manager any pretext for shuffling around the memory allocations, and
  29. change its master pointers. That's why it's OK to dereference the pixmap handle,
  30. i.e. use a local copy of the pixmap's master pointer.
  31.  
  32. All the routines in this file call either SetPixmapPixel or GetPixmapPixel. Both
  33. run fast by caching the information that they get about your Bit/Pixmap from
  34. RectToAddress. SetPixmapPixel and GetPixmapPixel each have their own cache.
  35.  
  36. HISTORY:
  37. 4/4/89    dgp wrote it as SetIPixel.c
  38. 9/8/90    dgp updated to work with 32 bit QuickDraw, if present.
  39. 10/15/90 bf renamed SetIPixelGW.c and modified for drawing to off screen pix maps.
  40. 4/26/92    dgp    Merged the two variants: SetIPixel.c and SetIPixelGW.c to produce the
  41.             new file SetOnePixel.c. 
  42.             Renamed SetIPixelGW to SetPixmapPixel.
  43.             Renamed GetIPixelGW to GetPixmapPixel.
  44.             Renamed SetIPixel to SetDevicePixel.
  45.             Renamed GetIPixel to GetDevicePixel.
  46.             Added SetOnePixel and GetOnePixel.
  47.             Generalized to handle any pixelSize, and accept bitmaps as well
  48.             as pixmaps.
  49. 12/23/92 dgp Doubled the speed of SetPixmapPixel and GetPixmapPixel (and thus sped up
  50.             all the routines that call them) by caching the answers from RectToAddress. 
  51.             The cache doubles the speed, but see CAUTION above.Introduced compile-time 
  52.             flag to optionally disable this new cache.
  53. 1/6/93 dgp    Fixed tiny but disastrous bug in GetPixmapPixel (wasn't saving old x and y).
  54. 1/22/93    dgp    Check more PixMap fields to make sure cache is not stale. Deleted the
  55.             warning about stale caches from the documentation.
  56. 2/7/93    dgp Wrote SetPixelsQuickly.c.
  57. 7/9/93    dgp check for 32-bit addressing capability.
  58. 6/18/94    dgp    can32 is now computed by calling TrapAvailable(_SwapMMUMode), which 
  59.             returns the correct answer even on Macs with dirty ROMs.
  60. 5/23/95 dgp Apple changed the prototype in the header file from SwapMMUMode(char *) to 
  61.             SwapMMUMode(signed char *). To retain compatibility with both old and new
  62.             headers, I cast the argument (void *).
  63. */
  64. #include "VideoToolbox.h"
  65. #ifndef __TRAPS__
  66.     #include <Traps.h>        // _SwapMMUMode
  67. #endif
  68. #define USE_CACHE 1    // true or false
  69.  
  70. void SetOnePixel(int x,int y,unsigned long value)
  71. // Assumes (x,y) is in the local coordinate system of the current port.
  72. {
  73.     WindowPtr window;
  74.     PixMapPtr pm;
  75.     
  76.     GetPort(&window);
  77.     if(x<window->portRect.left || x>=window->portRect.right
  78.         || y<window->portRect.top || y>=window->portRect.bottom)return;
  79.     // Is it a CGrafPort or a GrafPort?
  80.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  81.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  82.     else                                         // It's a GrafPort,
  83.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  84.     SetPixmapPixel(pm,x,y,value);
  85. }
  86.  
  87. unsigned long GetOnePixel(int x,int y)
  88. // Assumes (x,y) is in the local coordinate system of the current port.
  89. {
  90.     WindowPtr window;
  91.     PixMapPtr pm;
  92.     
  93.     GetPort(&window);
  94.     if(x<window->portRect.left || x>=window->portRect.right
  95.         || y<window->portRect.top || y>=window->portRect.bottom)return 0;
  96.     // Is it a CGrafPort or a GrafPort?
  97.     if(((CGrafPtr)window)->portVersion<0)        // It's a CGrafPort,
  98.         pm = *((CGrafPtr)window)->portPixMap;    // pass pixmap ptr.
  99.     else                                         // It's a GrafPort,
  100.         pm = (PixMapPtr) &window->portBits;        // pass bitmap ptr.
  101.     return GetPixmapPixel(pm,x,y);
  102. }
  103.  
  104. void SetPixmapPixel(register PixMapPtr pmPtr,int x,int y,unsigned long value)
  105. // Pokes a value into a pixel of any size. Accepts either pixmap or bitmap.
  106. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  107. // Speed is enhanced by reusing the cached information from last time if it's the
  108. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  109. // You can force it to flush its cache by passing a NULL PixMap address.
  110. {
  111.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  112.     static int oldX,oldY;
  113.     static short rowBytes,logPixelSize,bitsOffset;
  114.     static unsigned char *pixelPtr;
  115.     static BitMap oldMap;
  116.     int shift;
  117.     unsigned char mask;
  118.     signed char mode32=true32b;
  119.     Rect r;
  120.     Boolean can32;
  121.  
  122.     can32=TrapAvailable(_SwapMMUMode);
  123.     if(!USE_CACHE || pmPtr!=oldPmPtr
  124.         || pmPtr->baseAddr!=oldMap.baseAddr 
  125.         || pmPtr->rowBytes!=oldMap.rowBytes 
  126.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  127.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  128.         // Cache is stale. Get fresh values.
  129.         short pixelSize;
  130.         SetRect(&r,x,y,x+1,y+1);
  131.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  132.         if(pixelPtr==NULL){
  133.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  134.             return;
  135.         }
  136.         oldPmPtr=pmPtr;
  137.         oldMap=*(BitMap *)pmPtr;
  138.         logPixelSize=Log2L(pixelSize);
  139.     }else{
  140.         // Cache is fresh. Merely correct for changes in x and y.
  141.         if(pixelPtr==NULL)return;
  142.         if(logPixelSize<3){
  143.             register long bits;
  144.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  145.             pixelPtr+=bits>>3;
  146.             bitsOffset=bits&7;
  147.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  148.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  149.     }
  150.     if(can32)SwapMMUMode((void *)&mode32);
  151.     switch(logPixelSize){
  152.         register unsigned char val;
  153.     case 0:
  154.         shift=8-1-bitsOffset;    // from right, instead of from left
  155.         mask=1<<shift;
  156.         val=((unsigned char)value<<shift)&mask;
  157.         mask=~mask;
  158.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  159.         break;
  160.     case 1:
  161.         shift=8-2-bitsOffset;    // from right, instead of from left
  162.         mask=3<<shift;
  163.         val=((unsigned char)value<<shift)&mask;
  164.         mask=~mask;
  165.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  166.         break;
  167.     case 2:
  168.         shift=8-4-bitsOffset;    // from right, instead of from left
  169.         mask=15<<shift;
  170.         val=((unsigned char)value<<shift)&mask;
  171.         mask=~mask;
  172.         *pixelPtr= *pixelPtr & mask | (unsigned char)val;
  173.         break;
  174.     case 3:
  175.         *pixelPtr=value;
  176.         break;
  177.     case 4:
  178.         *(unsigned short *)pixelPtr=value;
  179.         break;
  180.     case 5:
  181.         *(unsigned long *)pixelPtr=value;
  182.         break;
  183.     }
  184.     if(can32)SwapMMUMode((void *)&mode32);
  185.     oldX=x;
  186.     oldY=y;
  187. }
  188.  
  189. unsigned long GetPixmapPixel(register PixMapPtr pmPtr,int x,int y)
  190. // Returns the contents of a pixel of any size. Accepts either pixmap or bitmap.
  191. // Assumes (x,y) is in the coordinate system of the bit/pixmap.
  192. // Speed is enhanced by reusing the cached information from last time if it's the
  193. // same Pix/Bitmap as last time, i.e. same address, baseAddr,rowBytes, and bounds.
  194. // You can force it to flush its cache by passing a NULL PixMap address.
  195. {
  196.     static PixMapPtr oldPmPtr=(PixMapPtr)-1;
  197.     static int oldX,oldY;
  198.     static short rowBytes,logPixelSize,bitsOffset;
  199.     static unsigned char *pixelPtr;
  200.     static BitMap oldMap;
  201.     int shift;
  202.     signed char mode32=true32b;
  203.     Rect r;
  204.     unsigned long value;
  205.     Boolean can32;
  206.  
  207.     can32=TrapAvailable(_SwapMMUMode);
  208.     if(!USE_CACHE || pmPtr!=oldPmPtr
  209.         || pmPtr->baseAddr!=oldMap.baseAddr 
  210.         || pmPtr->rowBytes!=oldMap.rowBytes 
  211.         || *(long *)&pmPtr->bounds.top!=*(long *)&oldMap.bounds.top
  212.         || *(long *)&pmPtr->bounds.bottom!=*(long *)&oldMap.bounds.bottom){
  213.         // Cache is stale. Get fresh values.
  214.         short pixelSize;
  215.         
  216.         SetRect(&r,x,y,x+1,y+1);
  217.         pixelPtr=RectToAddress(pmPtr,&r,&rowBytes,&pixelSize,&bitsOffset);
  218.         if(pixelPtr==NULL){
  219.             oldPmPtr=(PixMapPtr)-1;    // invalidate cache
  220.             return 0;
  221.         }
  222.         oldPmPtr=pmPtr;
  223.         oldMap=*(BitMap *)pmPtr;
  224.         logPixelSize=Log2L(pixelSize);
  225.     }else{
  226.         // Is already in cache. Merely correct for changes in x and y.
  227.         if(pixelPtr==NULL)return 0;
  228.         if(logPixelSize<3){
  229.             register long bits;
  230.             bits=bitsOffset+(long)(x-oldX)<<logPixelSize;
  231.             pixelPtr+=bits>>3;
  232.             bitsOffset=bits&7;
  233.         }else pixelPtr+=(x-oldX)<<(logPixelSize-3);
  234.         if(y!=oldY)pixelPtr+=(long)(y-oldY)*rowBytes;
  235.     }
  236.     if(can32)SwapMMUMode((void *)&mode32);
  237.     switch(logPixelSize){
  238.     case 0:
  239.         shift=8-1-bitsOffset;    // from right, instead of from left
  240.         value=*pixelPtr>>shift & 1;
  241.         break;
  242.     case 1:
  243.         shift=8-2-bitsOffset;    // from right, instead of from left
  244.         value=*pixelPtr>>shift & 3;
  245.         break;
  246.     case 2:
  247.         shift=8-4-bitsOffset;    // from right, instead of from left
  248.         value=*pixelPtr>>shift & 15;
  249.         break;
  250.     case 3:
  251.         value=*pixelPtr;
  252.         break;
  253.     case 4:
  254.         value=*(unsigned short *)pixelPtr;
  255.         break;
  256.     case 5:
  257.         value=*(unsigned long *)pixelPtr;
  258.         break;
  259.     }
  260.     if(can32)SwapMMUMode((void *)&mode32);
  261.     oldX=x;
  262.     oldY=y;
  263.     return value;
  264. }
  265.  
  266. void SetDevicePixel(GDHandle device,int x,int y,unsigned long value)
  267. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  268. {
  269.     if(device==NULL)return;
  270.     x+=(*(*device)->gdPMap)->bounds.left;
  271.     y+=(*(*device)->gdPMap)->bounds.top;
  272.     SetPixmapPixel(*(*device)->gdPMap,x,y,value);
  273. }
  274.  
  275. unsigned long GetDevicePixel(GDHandle device,int x,int y)
  276. // Assumes (x,y) is relative to the upper left hand corner of the screen.
  277. {
  278.     if(device==NULL)return 0;
  279.     x+=(*(*device)->gdPMap)->bounds.left;
  280.     y+=(*(*device)->gdPMap)->bounds.top;
  281.     return GetPixmapPixel(*(*device)->gdPMap,x,y);
  282. }
  283.  
  284. /*
  285. // Slightly faster than RectToAddress, but much less general. 
  286. // Requires 8-bit pixelSize. It will give wrong answer when
  287. // the pixmap is derived from a window in a multi-screen environment.
  288. unsigned char *GetPixmapPixelAddress(PixMapPtr pmPtr,int x,int y)
  289. {
  290.     register unsigned char *pixelPtr;
  291.     
  292.     if(!(pmPtr->rowBytes & 0x8000) || pmPtr->pixelSize != 8) {
  293.         PrintfExit("GetPixmapPixelAddress(): sorry, I require 8 bits/pixel.\007\n");
  294.     }
  295.     if(x<pmPtr->bounds.left || x>=pmPtr->bounds.right
  296.         || y<pmPtr->bounds.top || y>=pmPtr->bounds.bottom)return NULL;
  297.     x-=pmPtr->bounds.left;
  298.     y-=pmPtr->bounds.top;
  299.     pixelPtr=(unsigned char *)pmPtr->baseAddr;
  300.     pixelPtr+=y*(long)(pmPtr->rowBytes & 0x1fff);
  301.     pixelPtr+=x;
  302.     return pixelPtr;
  303. }
  304. */
  305.